package cn.zbh.user.service.impl;

import cn.zbh.basic.constant.RegisterConstant;
import cn.zbh.basic.domain.LoginData;
import cn.zbh.basic.exception.BusinessException;
import cn.zbh.basic.jwt.JwtUtils;
import cn.zbh.basic.jwt.RsaUtils;
import cn.zbh.basic.util.AjaxResult;
import cn.zbh.basic.util.HttpUtil;
import cn.zbh.basic.util.Md5Utils;

import cn.zbh.basic.util.StrUtils;
import cn.zbh.org.mapper.EmployeeMapper;
import cn.zbh.system.domain.Menu;
import cn.zbh.user.constant.WxConstants;
import cn.zbh.user.domain.Logininfo;
import cn.zbh.user.domain.User;
import cn.zbh.user.domain.WxUser;
import cn.zbh.user.dto.LoginDto;
import cn.zbh.user.dto.WxDto;
import cn.zbh.user.mapper.LogininfoMapper;
import cn.zbh.user.mapper.UserMapper;
import cn.zbh.user.mapper.WxUserMapper;
import cn.zbh.user.service.ILoginService;

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.security.PrivateKey;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@Service
public class LoginServiceImpl implements ILoginService {
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private WxUserMapper wxUserMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private EmployeeMapper employeeMapper;
    @Override
    public Map<String, Object> account(LoginDto dto) {
        //根据手机号和type查询logininfo

        Logininfo logininfo=logininfoMapper.getDto(dto);
        if(logininfo==null){
            //用户不存在
            throw new BusinessException("账号或密码错误");
        }
        //判断密码是否正确 加盐加密
        String s = Md5Utils.encrypByMd5(logininfo.getSalt() + dto.getPassword());
        if(!logininfo.getPassword().equals(s)){
            throw new BusinessException("账号或密码错误2");
        }
        //把数据保存在redis中 设置过期时间
    /*    //随机生成一个key
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token,logininfo,1, TimeUnit.MINUTES);
        //准备一个map
        HashMap<String, Object> map = new HashMap<>();
        //把盐值和密码设置为null

        logininfo.setSalt(null);
        logininfo.setPassword(null);


        map.put("token",token);
        map.put("logininfo",logininfo);*/


        Map<String,Object> map=loginSuccessJwtHandler(logininfo);

        return map;
    }

    private Map<String, Object> loginSuccessJwtHandler(Logininfo logininfo) {

        try {
            LoginData loginData = new LoginData();
            loginData.setLogininfo(logininfo);
            Map<String, Object> map = new HashMap<>();
            // 判断登录人是否是管理人员，
            if(logininfo.getType()==0){ // 管理人员
                // 返回当前登录人的权限
                List<String> permissions = employeeMapper.loadPermissionsByLogininfoId(logininfo.getId());

                // 当前登录人所有菜单
                List<Menu> menus = employeeMapper.loadMenusByLogininfoId(logininfo.getId());

                // 存入loginData
                loginData.setMenus(menus);
                loginData.setPermissions(permissions);

                // 存入map
                map.put("permissions",permissions);
                map.put("menus",menus);
            }

            //  加密
            //4.通过私钥对登录信息进行加密 - jwtToken串
            PrivateKey privateKey = RsaUtils.getPrivateKey(RsaUtils.class.getClassLoader()                                             	  .getResource("auth_rsa.pri").getFile());
            //将登陆人信息加密得到jwtToken串
            String jwtToken = JwtUtils.generateTokenExpireInMinutes(loginData, privateKey, 3000);

            map.put("token",jwtToken);
            map.put("logininfo",logininfo);

            return map;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }



    /**
     * 微信登录
     * @param code
     * @return
     */
    @Override
    public AjaxResult weChat(String code) {

        /**
         * 之前有绑定
         * 根据code获取token和openID
         * 根据openID查询 存在之前就绑定过 免密登录
         *
         */
        //发送请求 调工具类     jsonStr:json字符串
        String jsonStr = HttpUtil.httpGet(WxConstants.GET_ACK_URL
                .replace("APPID", WxConstants.APPID)
                .replace("SECRET", WxConstants.SECRET)
                .replace("CODE", code));
        //获取token和openid   将字符串转为json对象
        JSONObject jsonObject = JSONObject.parseObject(jsonStr);

        String access_token = jsonObject.getString("access_token");
        String openid = jsonObject.getString("openid");
       // System.out.println(access_token);
        //根据openID查询wxuser对象
        WxUser dbwxUser= wxUserMapper.findByOpenid(openid);

        //免密登录
        if(dbwxUser!=null && dbwxUser.getUser_id()!=null){

            //根据userID查询logininfo信息
            Logininfo logininfo=logininfoMapper.findByUserid(dbwxUser.getUser_id());

            //把数据保存在redis中 设置过期时间
            //随机生成一个key
            /*String token = UUID.randomUUID().toString();
            redisTemplate.opsForValue().set(token,logininfo,1, TimeUnit.MINUTES);
            //准备一个map
            HashMap<String, Object> map = new HashMap<>();
            //把盐值和密码设置为null

            logininfo.setSalt(null);
            logininfo.setPassword(null);


            map.put("token",token);
            map.put("logininfo",logininfo);*/
            Map<String,Object> map=loginSuccessJwtHandler(logininfo);
            return AjaxResult.me().setResultObj(map);
        }else{//第一次扫码
            //第三次发送请求
            String parm="?accessToken="+access_token+"&openId="+openid;
            return AjaxResult.me().setMsg("绑定").setResultObj(parm);
        }



    }

    @Override
    public AjaxResult binder(WxDto dto) {
        /**
         *1.校验：非空   验证码 超时  是否过期
         * 2.业务 user wxuser logininfo
         *向微信开放平台获取第三次请求 获取用户信息
         *
         * 通过手机号查询 用户信息 能查到 直接绑定
         * 未查到  自己生成一个user 在绑定
         */

        String verifyCode = dto.getVerifyCode();
        String accessToken = dto.getAccessToken();
        String openId = dto.getOpenId();
        String phone = dto.getPhone();
        if(StringUtils.isEmpty(verifyCode)||
                StringUtils.isEmpty(accessToken)||
                StringUtils.isEmpty(openId)||
                StringUtils.isEmpty(phone)
        ){
            throw new BusinessException("输入为空");
        }
        //校验验证码
        Object jsonObj = redisTemplate.opsForValue().get(phone + RegisterConstant.WXBINDER);
        if(jsonObj==null){
            throw new BusinessException("验证码过期");
        }
        if(!verifyCode.equalsIgnoreCase(jsonObj.toString().split(":")[0])){
            throw new BusinessException("验证码输入错误");
        }
        /**
         * *向微信开放平台获取第三次请求 获取用户信息
         *          *
         *          * 通过手机号查询 用户信息 能查到 直接绑定
         *          * 未查到  自己生成一个user 在绑定
         */
//public static final String GET_USER_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
        String json = HttpUtil.httpGet(WxConstants.GET_USER_URL
                .replace("ACCESS_TOKEN", accessToken)
                .replace("OPENID", openId));

        WxUser wxUser=json2wxuser(json);
// 通过手机号查询 用户信息 能查到 直接绑定
        User dbuser = userMapper.getPhone(phone);
        //没查到
        if(dbuser==null){
            //获取dbuser
            dbuser=phoneByUser(phone);
            //获取logininfo
            Logininfo logininfo=user2logininfo(dbuser);

            //保存logininfo 返回自增长主键
            logininfoMapper.add(logininfo);
            //保存user 返回自增主键
            dbuser.setLogininfo_id(logininfo.getId());
            userMapper.add(dbuser);

        }

        wxUser.setUser_id(dbuser.getId());
        wxUserMapper.add(wxUser);

        //免密登录
        //把数据保存在redis中 设置过期时间
        //随机生成一个key

        //通过dbuser获取logininfo对象
        Logininfo logininfo = logininfoMapper.findById(dbuser.getLogininfo_id());
/*
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token,logininfo,1, TimeUnit.MINUTES);
        //准备一个map
        HashMap<String, Object> map = new HashMap<>();
        //把盐值和密码设置为null

        logininfo.setSalt(null);
        logininfo.setPassword(null);


        map.put("token",token);
        map.put("logininfo",logininfo);*/
        Map<String,Object> map=loginSuccessJwtHandler(logininfo);
        return AjaxResult.me().setResultObj(map);

    }
    //生成一个logininfo
    private Logininfo user2logininfo(User dbuser) {
        Logininfo logininfo = new Logininfo();
        BeanUtils.copyProperties(dbuser,logininfo);
        return logininfo;
    }

    //生成一个User
    private User phoneByUser(String phone) {
        User user = new User();
        user.setUsername(phone);
        user.setPhone(phone);
        //生成一个盐值和密码
        String salt = StrUtils.getComplexRandomString(32);
        user.setSalt(salt);

        String password = StrUtils.getComplexRandomString(4);
        //加密
        String md5 = Md5Utils.encrypByMd5(salt + password);
        user.setPassword(md5);

        return user;
    }

    //返回一个wxuser对象   开放平台查参数
    private WxUser json2wxuser(String json) {
        WxUser wxUser = new WxUser();
        JSONObject jsonObject = JSONObject.parseObject(json);
        wxUser.setNickname(jsonObject.getString("xx"));
        wxUser.setSex(jsonObject.getInteger("sex"));
        wxUser.setAddress(jsonObject.getString("country"));
        wxUser.setHeadimgurl(jsonObject.getString("headimgurl"));
        wxUser.setUnionid(jsonObject.getString("setUnionid"));
        wxUser.setOpenid(jsonObject.getString("openid"));
        return wxUser;

    }

}
